package rmmk.algorithms.knn.math;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import rmmk.algorithms.features.FeatureManager;
import rmmk.framework.Utils;
import rmmk.framework.datasources.Document;

public class MinMax {
	Logger logger = LoggerFactory.getLogger(MinMax.class);
	public static Object sync = new Object();

	public Double[][] getMinMaxVector(List<Document> documents,
			FeatureManager fm) {
		int vectorLength = fm.getVectorLenght();

		Double[][] minMax = new Double[vectorLength][];

		ArrayList<Thread> threads = new ArrayList<>();
		int cores = Utils.getProcessorsCount();

		for (int i = 0; i < cores; ++i) {
			threads.add(new Thread(new MinMaxImpl(cores, i, 
					Collections.synchronizedList(documents), minMax, fm)));
			threads.get(threads.size()-1).start();
		}
		
		for (Thread t : threads)
			try {
				t.join();
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}

		return minMax;
	}

	private class MinMaxImpl implements Runnable {

		private int cores, shift;
		private List<Document> documents;
		private Double[][] array;
		private FeatureManager fm;

		public MinMaxImpl(int cores, int shift, List<Document> documents,
				Double[][] array, FeatureManager fm) {
			this.cores = cores;
			this.shift = shift;
			this.documents = documents;
			this.fm = fm;
			this.array = array;
		}

		@Override
		public void run() {
			//logger.info("Min max start");
			for (int x = shift; x < fm.getVectorLenght(); x+=cores){
					Double[] mmVal = minMax(documents, x, fm);
					
					synchronized(MinMax.sync)
					{
						array[x] = mmVal;
					}
					//logger.info("Min max: " + x + " wątek: " + shift);
			}
		}

		private Double[] minMax(List<Document> documents, int shift,
				FeatureManager fm) {
			Double min = Double.MAX_VALUE, max = Double.MIN_NORMAL;

			int documentsSize = documents.size();
			
			for (int i = 0; i < documentsSize; ++i) {
				Double[] vector = fm.calculateFeatureFor(documents.get(i));

				if (vector[shift] < min)
					min = vector[shift];
				if (vector[shift] > max)
					max = vector[shift];
				
				//logger.info("minmax: " + i );
			}

			Double[] ret = new Double[] { min, max };

			return ret;
		}
	}
}
